package com.zmj.sy.mom.srv.aps.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.PartPallet;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.*;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BasePageResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectItemResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.station.*;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.MkBeanUtils;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import com.zmj.sy.mom.srv.aps.utils.WorkshopProp;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class StationService {

    private final StationMapper stationMapper;

    private final WeekdaySchemeMapper weekdaySchemeMapper;

    private final WeekdayRuleMapper weekdayRuleMapper;

    private final StationWeekdaySchemeMapper stationWeekdaySchemeMapper;

    private final StationWeekdayRuleMapper stationWeekdayRuleMapper;

    private final ObjectMapper objectMapper;

    private final PartPalletMapper partPalletMapper;

    @Transactional
    public void add(StationAddReqVo reqVo) {
        Station station = MkBeanUtils.copyProperties(reqVo, Station.class);
        stationMapper.insert(station);

        addScheme(reqVo.getWeekdaySchemeId(), station);

    }

    @Transactional
    public void editMachine(StationEditMachineReqVo reqVo) {
        Station station = stationMapper.selectById(reqVo.getId());
        MkBeanUtils.copyPropertiesIgnore(reqVo, station);
        stationMapper.updateById(station);
    }

    public BasePageResVo<StationListResVo> list(StationListReqVo reqVo) {
        LambdaQueryWrapper<Station> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.hasText(reqVo.getName()), Station::getName, reqVo.getName());
        wrapper.like(StringUtils.hasText(reqVo.getMyCode()), Station::getMyCode, reqVo.getMyCode());
        Page<Station> shiftTypePage = stationMapper.selectPage(reqVo.toPage(), wrapper);

        BasePageResVo<StationListResVo> resVo = BasePageResVo.of(shiftTypePage, StationListResVo.class);

        for (StationListResVo datum : resVo.getData()) {
//            StationWeekdayScheme scheme = stationWeekdaySchemeMapper.selectOne(Wrappers.<StationWeekdayScheme>lambdaQuery().eq(StationWeekdayScheme::getStationId, datum.getId()));
            datum.setWeekdaySchemeId(datum.getShiftTypeId());
            datum.setOrgSchemeId(datum.getShiftTypeId());
        }

        return resVo;
    }

    public StationGetMachineResVo getMachine(BaseIdReqVo reqVo) {
        Station station = stationMapper.selectById(reqVo.getId());
        return MkBeanUtils.copyProperties(station, StationGetMachineResVo.class);
    }

    public StationGetResVo get(BaseIdReqVo reqVo) {
        Station station = stationMapper.selectById(reqVo.getId());
        return MkBeanUtils.copyProperties(station, StationGetResVo.class);
    }

    @Transactional
    public void edit(StationEditReqVo reqVo) {
        Station station = stationMapper.selectById(reqVo.getId());
        MkBeanUtils.copyPropertiesIgnore(reqVo, station);
        stationMapper.updateById(station);


        addScheme(reqVo.getWeekdaySchemeId(), station);
    }

    public void addScheme(Integer schemeId, Station station) {
        if (schemeId != null) {
//            station.setWeekdaySchemeId(reqVo.getWeekdaySchemeId());
            StationWeekdayScheme stationWeekdayScheme = stationWeekdaySchemeMapper.selectOne(Wrappers.<StationWeekdayScheme>lambdaQuery().eq(StationWeekdayScheme::getStationId, station.getId()));
            if (stationWeekdayScheme != null && stationWeekdayScheme.getSchemeId() != null && stationWeekdayScheme.getId().equals(schemeId)) {
                return;
            }
            if (stationWeekdayScheme != null) {
                stationWeekdaySchemeMapper.deleteById(stationWeekdayScheme.getId());
                stationWeekdayRuleMapper.delete(Wrappers.<StationWeekdayRule>lambdaQuery().eq(StationWeekdayRule::getStationId, station.getId()));
            }

            stationWeekdayScheme = new StationWeekdayScheme();


            WeekdayScheme ws = weekdaySchemeMapper.selectById(schemeId);
            MkBeanUtils.copyPropertiesIgnore(ws, stationWeekdayScheme);

            List<WeekdayRule> weekdayRules = weekdayRuleMapper.selectList(Wrappers.<WeekdayRule>lambdaQuery().eq(WeekdayRule::getWeekdaySchemeId, ws.getId()));
            List<StationWeekdayRule> collect = weekdayRules.stream()
                    .map(e -> {
                        StationWeekdayRule rule = new StationWeekdayRule();
                        MkBeanUtils.copyPropertiesIgnore(e, rule);
                        return rule;
                    })
                    .collect(Collectors.toList());

            stationWeekdayScheme.setStationId(station.getId());
            stationWeekdayScheme.setSchemeId(ws.getId());
            stationWeekdaySchemeMapper.insert(stationWeekdayScheme);

            for (StationWeekdayRule stationWeekdayRule : collect) {
                stationWeekdayRule.setStationId(station.getId());
                stationWeekdayRule.setStationWeekdaySchemeId(stationWeekdayScheme.getId());
                stationWeekdayRuleMapper.insert(stationWeekdayRule);
            }

        }
    }

    @Transactional
    public void delete(BaseIdReqVo reqVo) {
        stationMapper.deleteById(reqVo.getId());
    }

    @SneakyThrows
    public StationGetRuleResVo getRule(BaseIdReqVo reqVo) {
        Station station = stationMapper.selectById(reqVo.getId());
        String attr = station.getAttr();
        List<StationGetRuleItemResVo> list = new ArrayList<>();

        if (StringUtils.hasText(attr)) {
            try {
                list = objectMapper.readValue(attr, new TypeReference<ArrayList<StationGetRuleItemResVo>>() {});
            } catch (Exception e) {
                log.info("id为[{}]的属性转换失败，属性为[{}]", reqVo.getId(), attr);
            }
        }

        StationGetRuleResVo resVo = new StationGetRuleResVo();
        resVo.setId(reqVo.getId());
        resVo.setRules(list);
        return resVo;
    }

    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public void editRule(StationEditRuleReqVo reqVo) {
        Station station = stationMapper.selectById(reqVo.getId());
        String attr = objectMapper.writeValueAsString(reqVo.getRules());
        station.setAttr(attr);
        stationMapper.updateById(station);
    }

    public BaseSelectResVo select(BaseIdReqVo reqVo) {

        List<Station> stationList = null;

        if(reqVo.getId() != null){

            QueryWrapper<Station> query = Wrappers.query();
            query.eq("g.id ", reqVo.getId());
            stationList = stationMapper.findByGroupId(query);
        } else {
            stationList = stationMapper.query().list();
        }

        List<BaseSelectItemResVo> collect = stationList.stream()
                .map(e -> {
                    BaseSelectItemResVo item = new BaseSelectItemResVo();
                    item.setText(e.getName());
                    item.setValue(e.getId());
                    item.getAttr().put("myCode", e.getMyCode());
                    return item;
                })
                .collect(Collectors.toList());

        return BaseSelectResVo.of(collect);
    }

    @Transactional
    public void partIn(StationPartInReqVo reqVo) {
        PartPallet one = partPalletMapper.lambdaQuery()
                .eq(PartPallet::getUniqueCode, reqVo.getUniqueCode())
                .one();
        if (one == null) {
            throw SyExceptionUtils.e("该零件不存在");
        }
        if (one.getPositionCode()!= null) {
            throw SyExceptionUtils.e("该零件已经在工位[" + one.getPositionCode() + "]上");
        }
        one.setPositionCode(reqVo.getStationCode());
        partPalletMapper.updateById(one);

    }

    @Transactional
    public void partOut(StationPartOutReqVo reqVo) {
        PartPallet one = partPalletMapper.lambdaQuery()
                .eq(PartPallet::getUniqueCode, reqVo.getUniqueCode())
                .one();

        if (one == null) {
            throw SyExceptionUtils.e("该零件不存在");
        }

        if (one.getPositionCode() == null) {
            throw SyExceptionUtils.e("该零件已经不在工位上");
        }
        partPalletMapper.lambdaUpdate()
                .eq(PartPallet::getUniqueCode, reqVo.getUniqueCode())
                .set(PartPallet::getPositionCode, null)
                .update();
    }
    public String getStaffCode(String staffCode, String stationCode) {
        if (!StringUtils.hasText(staffCode) || WorkshopProp.DEFAULT_USER.equalsIgnoreCase(staffCode)|| "--".equalsIgnoreCase(staffCode) || "workshop".equalsIgnoreCase(staffCode)) {
            try {
              /*  Group group = groupMapper.selectOne(new QueryWrapper<Group>().eq("my_code", stationCode));
                if (ObjectUtils.isEmpty(group)) {
                    group = groupMapper.selectGroupByWorkPlace(Wrappers.<Group>query()
                            .eq("ts.my_code",stationCode));
                }*/
//                Result<WorkPlaceUserVo> vo = staffApiClient.getPublicCodeByStation(stationCode);
//                if (vo.getData() != null) {
//                    return vo.getData().getPublicCode();
//                }
                final List<Station> stationList = stationMapper.lambdaQuery().eq(Station::getMyCode, stationCode).list();
                if (!ObjectUtils.isEmpty(stationList)) {
                    return stationList.get(0).getStaffCode();
                }
            } catch (Exception e) {
            }
        }else if(StringUtils.hasText(staffCode)){
            return  staffCode;
        }
        return null;
    }


}
